#ifndef LAZY_H
#define LAZY_H

#include <functional>
#include <memory>

// 帮助类，用于延迟初始化对象(objects).
// 使用方式1:
//    Lazy<Foo> my_lazy_object([]() { return new Foo; });
// 使用方式2:
//    Lazy<Foo> my_lazy_object([]() { return new Foo; },
//                             [](Foo *foo) { delete foo; });
template <typename T>
class Lazy {
public:
    explicit Lazy(std::function<T*()> init,
                  std::function<void(T*)> deleter = Lazy::default_deleter)
        : init_(init), ptr_(nullptr, deleter) {}

    // Convenience constructor that will lazily default construct the object.
    Lazy()
        : init_([]() { return new T; }),
          ptr_(nullptr, Lazy::default_deleter)
    {

    }

    T* get() const {
        CheckInitialised();
        return ptr_.get();
    }

    /* 对取值操作符* 进行了重载 */
    typename std::add_lvalue_reference<T>::type operator*() const {
        CheckInitialised();
        return *ptr_;
    }

    /*  对操作符 -> 进行了重载 */
    T* operator->() const { return get(); }

    // operator bool () 提供一个本类型到bool的隐式转换，不允许使用参数
    explicit operator bool() const { return ptr_; }


    void reset() { ptr_.reset(nullptr); }

    static void default_deleter(T* obj) { delete obj; }

private:
    void CheckInitialised() const {

        //指针为NULL,
        if (!ptr_) {
            ptr_.reset(init_());
        }
    }

    const std::function<T*()> init_;

    mutable std::unique_ptr<T, std::function<void(T*)>> ptr_;
};


#endif // LAZY_H
